package com.surfilter.phantomjs.util;

import com.surfilter.exception.OprateException;
import com.surfilter.phantomjs.manage.PhantomJSDriverPools;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.openqa.selenium.*;
import org.openqa.selenium.phantomjs.PhantomJSDriver;
import org.openqa.selenium.remote.UnreachableBrowserException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class WebCrawlUtils {

    private static final Logger logger = LoggerFactory.getLogger(WebCrawlUtils.class);

    private PhantomJSDriver driver;

    private Long time_out = 40 * 60 * 1000l;

    public WebCrawlUtils() {
        super();
    }

    public WebCrawlUtils(PhantomJSDriver driver) {
        super();
        this.driver = driver;
    }

    public boolean initDriverByPools() throws OprateException, InterruptedException{
        driver = PhantomJSDriverPools.getPhantomJSDriver(time_out);
        return initStatus();
    }

    public boolean initDriverByPoolsDefault() throws OprateException, InterruptedException{
        driver = PhantomJSDriverPools.getPhantomJSDriverByDefaultTime();
        return initStatus();
    }

    public boolean initDriverDefault(){
        driver = HttpUtil.getPhantomJSDriver();
        return initStatus();
    }

    public boolean initDriver(Platform plat, String browserName, boolean javasriptenabled, String phantomjsPath, Map<String, Object> capabilitys, String[] phantomJsArgs, Integer dimensionW, Integer dimensionH){
        driver = HttpUtil.getPhantomJSDriver(plat, browserName, javasriptenabled, phantomjsPath, capabilitys, phantomJsArgs, dimensionW, dimensionH);
        return initStatus();
    }

    public boolean initStatus(){
        if(driver != null)return true;
        return false;
    }

    public String getCurrentUrl(){
        return driver.getCurrentUrl();
    }

    public String getWindowhandle(){
        return driver.getWindowHandle();
    }

    public String getSessionId(){
        if(driver != null)
            return driver.getSessionId().toString();
        return null;
    }

    public boolean openWebPage(String url){
        while(true){
            try{
                driver.navigate().to(url);
                return true;
            }catch(TimeoutException te){
                logger.error("打开网站:{}超时...{}", url, te);
                return false;
            }catch(UnreachableBrowserException e){
                PhantomJSDriverPools.reopenPhantomJSDriver(driver);
                try {
                    initDriverByPools();
                } catch (OprateException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                } catch (InterruptedException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
            }
        }
    }

    public List<WebElement> findElementsByCssSelector(String selector){
        List<WebElement> eles = null;
        try{
            eles = driver.findElementsByCssSelector(selector);
        }catch(Exception e){
            logger.error("查找元素集：{}异常", selector, e);
        }
        return eles;
    }

    public void createNewWindow(String windowname){
        createNewWindow(windowname, "about:blank");
    }

    public void createNewWindow(String windowname, String url){
        try{
            ((JavascriptExecutor) driver).executeScript("window.open('" + url + "','" + windowname + "');");
        }catch(Exception e){
            logger.error("创建新的Window：{}异常", windowname, e);
        }
    }

    public List<WebElement> findElementsByXpath(String xpath){
        List<WebElement> eles = null;
        try{
            eles = driver.findElementsByXPath(xpath);
        }catch(Exception e){
            logger.error("查找元素集：{}异常", xpath, e);
        }
        return eles;
    }

    public List<WebElement> findElementsByTagName(String tagName){
        List<WebElement> eles = null;
        try{
            eles = driver.findElementsByTagName(tagName);
        }catch(Exception e){
            logger.error("查找元素集：{}异常", tagName, e);
        }
        return eles;
    }

    public List<WebElement> findElementsBy(By by){
        List<WebElement> eles = null;
        try{
            eles = driver.findElements(by);
        }catch(Exception e){
            logger.error("查找元素集：{}异常", by.toString(), e);
        }
        return eles;
    }

    public WebElement findElementBy(By by){
        WebElement result = null;
        try{
            result = driver.findElement(by);
        }catch(Exception e){
            logger.error("查找元素：{}异常", by.toString(), e);
        }
        return result;
    }

    public WebElement findElementByCssSelector(String selector){
        WebElement result = null;
        try{
            result = driver.findElementByCssSelector(selector);
        }catch(Exception e){
            logger.error("查找元素：{}异常", selector, e);
        }
        return result;
    }

    public WebElement findElementByCssSelector(WebElement ele, String selector){
        WebElement result = null;
        try{
            result = ele.findElement(By.cssSelector(selector));
        }catch(Exception e){
            logger.error("查找元素：{}异常", selector, e);
        }
        return result;
    }

    public WebElement findElementByXpath(String xpath){
        WebElement result = null;
        try{
            result = driver.findElementByXPath(xpath);
        }catch(Exception e){
            logger.error("查找元素：{}异常", xpath, e);
        }
        return result;
    }

    public void ajaxWait(long time){
        try {
            Thread.sleep(time);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public void click(WebElement ele){
        ele.click();
    }

    public void sendKeys(WebElement ele, CharSequence keysToSend){
        ele.sendKeys(keysToSend);
    }

    public BufferedImage createElementImage(WebElement webElement)
            throws IOException {
        Point location = webElement.getLocation();
        Dimension size = webElement.getSize();
        BufferedImage originalImage = ImageIO.read(new ByteArrayInputStream(takeScreenshot()));
        BufferedImage croppedImage = originalImage.getSubimage(location.getX(),
                location.getY(), size.getWidth(), size.getHeight());
        return croppedImage;
    }

    public byte[] takeScreenshot() throws IOException {
        TakesScreenshot takesScreenshot = (TakesScreenshot) driver;
        return takesScreenshot.getScreenshotAs(OutputType.BYTES);
    }

    public boolean cutCurrentSitePicture(String dest_dir, String fileName, String format){
        boolean result = false;
        try{
            byte[] images = takeScreenshot();
            File destfile = new File(dest_dir);
            if(!destfile.exists())destfile.mkdirs();
            File rdestFile = new File(dest_dir + "/" + fileName + format);
            if(rdestFile.exists())rdestFile.delete();
            FileUtils.writeByteArrayToFile(rdestFile, images);
            if(rdestFile.exists())result = true;
        }catch(Exception e){
            logger.error("截取当前页面图片异常", e);
        }
        return result;
    }

    public void switchToWindow(String windowName){
        driver.switchTo().window(windowName);
    }

    public void switchToFrame(WebElement frameElement){
        driver.switchTo().frame(frameElement);
    }

    public void recoveryDriver(){
        try {
            clear();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            logger.error("回收Driver异常", e);
        }finally{
            try {
                PhantomJSDriverPools.returnPhantomJSDriver(driver);
            } catch (OprateException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    public void clear(){
        String clear_url = "about:blank";
        openWebPage(clear_url);
    }

    public void close(){
        driver.close();
    }

    public void quit(){
        driver.quit();
    }

    public String getPageSource() {
        // TODO Auto-generated method stub
        return driver.getPageSource();

    }
    public  boolean writePictureByWebUrl( String destFileDir, String fileName, String keyword){
        boolean target = false;
        try{
            if(keyword != null && !keyword.trim().equalsIgnoreCase("")){
                driver.executeScript("window.find('" + keyword + "',false,false);", "");
            }
            byte[] images = driver.getScreenshotAs(OutputType.BYTES);
            File destfile = new File(destFileDir);
            if(!destfile.exists())destfile.mkdirs();
            File rdestFile = new File(destFileDir + "/" + fileName);
            if(rdestFile.exists())rdestFile.delete();
            FileUtils.writeByteArrayToFile(rdestFile, images);
            if(rdestFile.exists())target = true;
        }catch(Exception e){
            logger.error("WebCrawUtil中获取网页图片异常", e);
        }
        return target;
    }

    public List<String> getPageSourceAndFrame(String ym) {
        try {

            long start = System.currentTimeMillis();
            List <String> list = new ArrayList<String>();
            String pageSource = driver.getPageSource();
            list.add(pageSource);
            List<String> frames = getPageHtmlByjudegeFrame(ym);
            if(frames == null || frames.isEmpty())return list;
            list.addAll(frames);
            long end = System.currentTimeMillis();
            logger.info("测试--获取网站快照所需时间:{},{}毫秒",ym,end-start);
            return list;
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            logger.error("测试----获取网页源码快照报错..{}..{}",ym,e);
        }
        return null;

    }

    public List<String> getPageHtmlByjudegeFrame(String ym){
        List<String> list = new ArrayList<String>();
        try {
            List<WebElement> frameList = driver.findElementsByTagName("frame");
            List<WebElement> iframeList = driver.findElementsByTagName("iframe");
            if(frameList != null && !frameList.isEmpty()){
                for (WebElement webElement : frameList) {
                    String attribute = webElement.getAttribute("src");
                    System.out.println(attribute);
                    if(StringUtils.isEmpty(attribute) || "about:blank".equalsIgnoreCase(attribute.trim()) ||
                            !(attribute.contains("http:") || attribute.contains("https:")))continue;
                    WebDriver frame = driver.switchTo().frame(webElement);
                    String page = frame.getPageSource();
                    list.add(page);
                    List<String> list1 = getPageHtmlByjudegeFrame(ym);
                    list.addAll(list1);
                }
            }
            if(iframeList != null && !iframeList.isEmpty()){
                for (WebElement webElement : iframeList) {
                    String attribute = webElement.getAttribute("src");
                    System.out.println(attribute);
                    if(StringUtils.isEmpty(attribute) || "about:blank".equalsIgnoreCase(attribute.trim()) ||
                            !(attribute.contains("http:") || attribute.contains("https:")))continue;
                    WebDriver frame = driver.switchTo().frame(webElement);
                    String page = frame.getPageSource();
                    list.add(page);
                    List<String> list2 = getPageHtmlByjudegeFrame(ym);
                    list.addAll(list2);
                }
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            logger.error("测试---通过frame标签获取快照报错域名为：...{}...{}",ym,e);
        }
        return list;

    }


}
